package com.easy.common.util.file;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;

import com.alibaba.fastjson.JSON;
import com.easy.common.util.date.DateUtils;
import com.easy.common.util.string.StringUtil;
import com.easy.common.util.string.UUIDHexGenerator;

@WebServlet("/upload")
public class UploadServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	
	//上传到服务器的文件名原名
	private String srcName = null;
	//最后合并后的新文件名
	private String newName = null;
	
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setCharacterEncoding("UTF-8");
		Integer chunk = null;// 分割块数
		Integer chunks = null;// 总分割数
		BufferedOutputStream outputStream = null;
		
		//当前项目的上级目录HTTP（TOMCAT WEBAPPS目录）
		String web_root = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort() ;
		//当前项目的绝对路径
		String project_realpath = request.getServletContext().getRealPath("");
		//当前项目的上级目录的绝对路径
		String resroot = new File(project_realpath).getParent();
		
		//文件保存的绝对路径
		String saveDir = "" ;
		//分类目录
		String folderCategory = "" ;
		
		
		//文件是否保存到当前项目的上级目录，如果为null或者false则保存到当前项目中
		String pc = request.getParameter("pc") ;
		
		//文件存放的路径
		String upload_path = request.getParameter("upload_path") ;
		
		//是否创建分类目录（null/0：不创建分类目录，1：日期分类目录，2：文件类型分类目录）
		String folderType = request.getParameter("folderType") ;
		
		//文件的命名类型(0：原名，1：随机名32位，2：日期加随机)
		String fileNameType = request.getParameter("fileNameType") ;
		
		if(null != folderType && !"".equalsIgnoreCase(folderType) && !"0".equalsIgnoreCase(folderType)) {
			//日期分类目录
			if(folderType.equalsIgnoreCase("1")) {
				folderCategory =  File.separator + DateUtils.formatYYYYMMDD(new Date()) ;
			}
		}
		
		
		//判定是否将文件保存到当前项目
		if(null == pc || pc.equalsIgnoreCase("false")) {
			//保存到当前项目中
			saveDir = StringUtil.filePath(project_realpath + upload_path + folderCategory + File.separator) ;
			web_root += StringUtil.filePath(request.getContextPath() + File.separator +upload_path +File.separator + folderCategory + File.separator) ;
		} else {
			//保存到当前项目的上级目录
			saveDir = StringUtil.filePath(resroot + File.separator +upload_path + folderCategory + File.separator) ;
			web_root += StringUtil.filePath(File.separator + upload_path + folderCategory + File.separator) ;
		}
		
		FileForm f = new FileForm() ;
		Map<String, Object> map = new HashMap<String, Object>() ;
		map.put("status", false) ;
		map.put("msg", "文件上传失败！") ;
		
		//创建文件存储目录
		File up = new File(saveDir);
		if (!up.exists()) {
			up.mkdirs();
		}
		//创建文件临时存储目录
		File temp = new File(new File(resroot).getParent().toString()+File.separator+"file_temp") ;
		if (!temp.exists()) {
			temp.mkdirs();
		}
		
		if (ServletFileUpload.isMultipartContent(request)) {
			try {
				DiskFileItemFactory factory = new DiskFileItemFactory();
				factory.setSizeThreshold(1024);
				factory.setRepository(temp) ;
				ServletFileUpload upload = new ServletFileUpload(factory);
				upload.setHeaderEncoding("UTF-8");
				List<FileItem> items = upload.parseRequest(request);
				
				for (FileItem item : items) {
					
					if (item.isFormField()) {//是文本域
						if (item.getFieldName().equals("name")) {
							srcName = item.getString("utf-8");
						} else if (item.getFieldName().equals("chunk")) {
							chunk = Integer.parseInt(item.getString());
						} else if (item.getFieldName().equals("chunks")) {
							chunks = Integer.parseInt(item.getString());
						}
						
					} else {//如果是文件类型
						if (srcName != null) {
							//文件命名类型
							if(null != fileNameType && chunk == null || chunk == 0) {
								if(fileNameType.equals("1")) {
									newName = d_r_Name()+FilenameUtils.getExtension(srcName) ;
								} else if(fileNameType.equals("2")) {
									newName = UUIDHexGenerator.generator().toString()+"."+FilenameUtils.getExtension(srcName) ; ;
								} else if(fileNameType.equals("0")) {
									newName = srcName ;
								}
							}
							
							String chunkName = newName;
							if (chunk != null) {
								chunkName = chunk + "_" + newName;
							}
							//分块进行保存
							File savedFile = new File(saveDir, chunkName);
							item.write(savedFile);
						}
					}
				}
				
				//当文件分块上传完之后，将文件分块进行合并
				if (chunk != null && chunk + 1 == chunks) {
					//文件分块合并中...
					outputStream = new BufferedOutputStream(new FileOutputStream(new File(saveDir, newName)));
					// 遍历分块文件合并
					for (int i = 0; i < chunks; i++) {
						File tempFile = new File(saveDir, i + "_" + newName);
						
						byte[] bytes = FileUtils.readFileToByteArray(tempFile);
						outputStream.write(bytes);
						outputStream.flush();
						tempFile.delete();
					}
					outputStream.flush();
					//文件分块合并完毕...
				}
				
				f.setWeb_root(web_root) ;
				f.setProject_realpath(project_realpath) ;
				f.setWebroot_realpath(resroot) ;
				f.setUpload_path(upload_path) ;
				f.setSaveDir(saveDir) ;
				f.setSrcName(srcName) ;
				f.setNewName(newName) ;
				
				map.put("status", true) ;
				map.put("msg", "文件上传成功！") ;
				map.put("fileinfo", f) ;
				
			} catch (FileUploadException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (outputStream != null) {
					outputStream.close();
					srcName = null ;
					newName = null ;
				}
			}
		}
		response.getWriter().write(JSON.toJSONString(map));
	}
	
	/* 
     * 生成随机文件名 
     * 2014_5_4_随机数.
     */  
    public static String d_r_Name(){  
        String RandomFilename = "";  
        Random rand = new Random();//生成随机数  
        int random = rand.nextInt();  
          
        Calendar calCurrent = Calendar.getInstance();  
        int intDay = calCurrent.get(Calendar.DATE);  
        int intMonth = calCurrent.get(Calendar.MONTH) + 1;  
        int intYear = calCurrent.get(Calendar.YEAR);  
        String now = String.valueOf(intYear) + "_" + String.valueOf(intMonth) + "_" +  
            String.valueOf(intDay) + "_";  
          
        RandomFilename = now + String.valueOf(random > 0 ? random : ( -1) * random) + ".";  
          
        return RandomFilename;  
    }
	
}
